/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.mycompany.delivery.service;

import com.mycompany.delivery.dao.CourierDAO;
import com.mycompany.delivery.dao.DeliveryDAO;
import com.mycompany.delivery.dao.EmployeeDAO;
import com.mycompany.delivery.dto.DTOState;
import com.mycompany.delivery.dto.DeliveryDTO;
import com.mycompany.delivery.dto.UserDTO;
import com.mycompany.delivery.entities.Courier;
import com.mycompany.delivery.entities.Delivery;
import com.mycompany.delivery.entities.Employee;
import com.mycompany.delivery.entities.State;
import com.mycompany.delivery.servicelayer.DeliveryService;
import com.mycompany.delivery.transfers.DeliveryT;
import com.mycompany.delivery.transfers.EnumT;
import com.mycompany.delivery.transfers.UserT;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.annotation.Secured;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 *
 * @author Mato
 */
@Service("deliveryServices")
public class DeliveryServiceImpl implements DeliveryService {

    @Autowired
    private DeliveryDAO deliveryDao;

    @Autowired
    private CourierDAO courierDao;

    @Autowired
    private EmployeeDAO employeeDao;

    public CourierDAO getCourierDao() {
        return courierDao;
    }

    public void setCourierDao(CourierDAO courierDao) {
        this.courierDao = courierDao;
    }

    public DeliveryDAO getDeliveryDao() {
        return deliveryDao;
    }

    public void setDeliveryDao(DeliveryDAO deliveryDao) {
        this.deliveryDao = deliveryDao;
    }

    public EmployeeDAO getEmployeeDao() {
        return employeeDao;
    }

    public void setEmployeeDao(EmployeeDAO employeeDao) {
        this.employeeDao = employeeDao;
    }

    @Override
    @Transactional
    @Secured({"ROLE_EMPL", "ROLE_ADMIN"})
    public DeliveryDTO create(DeliveryDTO p) {
        if (p == null) {
            throw new IllegalArgumentException("Delivery is null");
        }
        if (p.getId() != null) {
            throw new IllegalArgumentException("Id must be null ");
        }
        Delivery d = DeliveryT.dTOtoEntity(p);
        if (p.getCourier() != null) {
            d.setCourier(courierDao.getCourierById(p.getCourier()));
        }

        if (p.getEmployee() != null) {
            d.setEmployee(employeeDao.getEmployeeById(p.getCourier()));
        }
        deliveryDao.createDelivery(d);
        p.setId(d.getId());

        return p;
    }

    @Override
    @Transactional
    @Secured({"ROLE_EMPL", "ROLE_COUR", "ROLE_ADMIN"})
    public DeliveryDTO update(DeliveryDTO p) {
        if (p == null) {
            throw new IllegalArgumentException("Delivery is null");
        }
        if (p.getId() == null) {
            throw new IllegalArgumentException("Id can't be null ");
        }
        
        Delivery d = DeliveryT.dTOtoEntity(p);
        if (p.getCourier() != null) {
            d.setCourier(courierDao.getCourierById(p.getCourier()));
        }

        if (p.getEmployee() != null) {
            d.setEmployee(employeeDao.getEmployeeById(p.getCourier()));
        }
        deliveryDao.updateDelivery(d);
        return p;
    }

    @Override
    @Transactional
    @Secured({"ROLE_EMPL", "ROLE_ADMIN"})
    public DeliveryDTO remove(DeliveryDTO p) {
        if (p == null) {
            throw new IllegalArgumentException("Delivery is null");
        }
        if (p.getId() == null) {
            throw new IllegalArgumentException("Id can't be null ");
        }
        if(p.getCourier() != null &&p.getCourier() !=0l ) {
            removeDeliveryFromCourier(p,UserT.EntityToDTO(courierDao.getCourierById(p.getCourier())));
        }
        
        if(p.getEmployee()!= null &&p.getEmployee() !=0l ) {
            removeDeliveryFromEmployee(p,UserT.EntityToDTO(employeeDao.getEmployeeById(p.getCourier())));
        }
        deliveryDao.deleteDelivery(DeliveryT.dTOtoEntity(p));
        return p;
    }

    @Override
    @Transactional
    @Secured({"ROLE_EMPL", "ROLE_COUR", "ROLE_ADMIN"})
    public DeliveryDTO find(Long id) {
        if (id == null) {
            throw new IllegalArgumentException("Id is null");
        }
        return DeliveryT.EntityToDTO(deliveryDao.getDeliveryById(id));
    }

    @Override
    @Transactional
    @Secured({"ROLE_EMPL", "ROLE_COUR", "ROLE_ADMIN"})
    public void addDeliveryToCourier(DeliveryDTO d, UserDTO c) {

        if (d.getId() == null) {
            throw new IllegalArgumentException("DeliveryDTO d is null");
        }
        if (c.getId() == null) {
            throw new IllegalArgumentException("UserDTO c is null");
        }

        c.addDelivery(d);
        d.setCourier(c.getId());
        Courier uu = UserT.dTOtoCourierEntity(c);
        Long employeId = 0l;
        if (d.getEmployee() != null) {
            employeId = d.getEmployee();
        }
        Delivery dd = DeliveryT.dTOtoEntity(d, employeeDao.getEmployeeById(employeId), uu);

        courierDao.updateCourier(uu);
        deliveryDao.updateDelivery(dd);
    }

    @Override
    @Transactional
    @Secured({"ROLE_EMPL", "ROLE_ADMIN"})
    public void addDeliveryToEmployee(DeliveryDTO d, UserDTO e) {

        if (d.getId() == null) {
            throw new IllegalArgumentException("DeliveryDTO d is null");
        }
        if (e.getId() == null) {
            throw new IllegalArgumentException("UserDTO e is null");
        }

        e.addDelivery(d);
        d.setEmployee(e.getId());
        Employee empl = UserT.dTOtoEmployeeEntity(e);
        Long courierID = 0l;
        if (d.getCourier() != null) {
            courierID = d.getCourier();
        }
        Delivery del = DeliveryT.dTOtoEntity(d, empl, courierDao.getCourierById(courierID));

        employeeDao.updateEmployee(empl);
        deliveryDao.updateDelivery(del);
    }

    @Override
    @Transactional
    @Secured({ "ROLE_ADMIN"})
    public void removeDeliveryFromCourier(DeliveryDTO d, UserDTO c) {

        if (d.getId() == null) {
            throw new IllegalArgumentException("DeliveryDTO d is null");
        }
        if (c.getId() == null) {
            throw new IllegalArgumentException("UserDTO c is null");
        }

        c.removeDelivery(d);
        d.setCourier(null);

       
        Courier uu = UserT.dTOtoCourierEntity(c);
        Long employeId = 0l;
        if (d.getEmployee() != null) {
            employeId = d.getEmployee();
        }
        Delivery del = DeliveryT.dTOtoEntity(d, employeeDao.getEmployeeById(employeId), uu);

        courierDao.updateCourier(uu);
        deliveryDao.updateDelivery(del);
    }

    @Override
    @Transactional
    @Secured({ "ROLE_ADMIN"})
    public void removeDeliveryFromEmployee(DeliveryDTO d, UserDTO e) {

        if (d.getId() == null) {
            throw new IllegalArgumentException("DeliveryDTO d is null");
        }
        if (e.getId() == null) {
            throw new IllegalArgumentException("UserDTO e is null");
        }

        e.removeDelivery(d);
        d.setEmployee(null);
        Employee empl = UserT.dTOtoEmployeeEntity(e);
        Long courierID = 0l;
        if (d.getCourier() != null) {
            courierID = d.getCourier();
        }
        Delivery del = DeliveryT.dTOtoEntity(d, empl, courierDao.getCourierById(courierID));

        if (d.getCourier() != null) {
            del.setCourier(courierDao.getCourierById(d.getCourier()));
        }
        if (d.getEmployee() != null) {
            del.setEmployee(null);
        }
        employeeDao.updateEmployee(empl);
        deliveryDao.updateDelivery(del);
    }

    @Override
    @Transactional
    @Secured({"ROLE_EMPL", "ROLE_COUR", "ROLE_ADMIN"})
    public List<DeliveryDTO> getDeliveriesByStateFromCourier(UserDTO u, DTOState s) {
        if (u.getId() == null) {
            throw new IllegalArgumentException("DeliveryDTO d is null");
        }
        State state = EnumT.DTOStateToState(s);
        List<DeliveryDTO> deliveries = new ArrayList<DeliveryDTO>();

        for (Delivery d : courierDao.getCourierById(u.getId()).getDeliveries()) {
            if (d.getState() == state) {
                deliveries.add(DeliveryT.EntityToDTO(d));
            }
        }

        return deliveries;
    }

    @Override
    @Transactional
    @Secured({"ROLE_EMPL", "ROLE_COUR", "ROLE_ADMIN"})
    public List<DeliveryDTO> getDeliveriesByStateFromEmployee(UserDTO u, DTOState s) {
        if (u.getId() == null) {
            throw new IllegalArgumentException("DeliveryDTO d is null");
        }
        State state = EnumT.DTOStateToState(s);
        List<DeliveryDTO> deliveries = new ArrayList<DeliveryDTO>();

        for (Delivery d : employeeDao.getEmployeeById(u.getId()).getCreatedDelivery()) {
            if (d.getState() == state) {
                deliveries.add(DeliveryT.EntityToDTO(d));
            }
        }

        return deliveries;
    }

    @Transactional
    @Override
    @Secured({"ROLE_EMPL", "ROLE_COUR", "ROLE_ADMIN"})
    public List<DeliveryDTO> getDeliveriesInUnprocessedState() {
        List<DeliveryDTO> deliveries = new ArrayList<DeliveryDTO>();
        for (Delivery d : deliveryDao.getAllDeliveries()) {
            if (d.getState() == State.NOTDELIVERED || d.getState() == State.RECEIVEDBYCOURIER ) {
                deliveries.add(DeliveryT.EntityToDTO(d));
            }
        }
        return deliveries;

    }

    @Transactional
    @Override
    @Secured({"ROLE_EMPL", "ROLE_COUR", "ROLE_ADMIN"})
    public List<DeliveryDTO> getDeliveriesInProcessedState() {
        List<DeliveryDTO> deliveries = new ArrayList<DeliveryDTO>();
        for (Delivery d : deliveryDao.getAllDeliveries()) {
            if (d.getState() == State.RECEIVEDBYCOURIER || d.getState() == State.NOTDELIVERED) {
                deliveries.add(DeliveryT.EntityToDTO(d));
            }
        }
        return deliveries;
    }

    @Transactional
    @Override
    @Secured({"ROLE_EMPL", "ROLE_COUR", "ROLE_ADMIN"})
    public List<DeliveryDTO> getDeliveriesWithoutCourier() {
        List<DeliveryDTO> deliveries = new ArrayList<DeliveryDTO>();
        for (Delivery d : deliveryDao.getAllDeliveries()) {
            if (d.getCourier() == null) {
                deliveries.add(DeliveryT.EntityToDTO(d));
            }
        }
        return deliveries;
    }
}
